package xyz.hzxiao.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import xyz.hzxiao.annotation.Limit;

import javax.servlet.http.HttpServletRequest;

/**
 * 限流
 *
 * @author ：FuXx
 * @className : xyz.hzxiao.aop.LimitAop
 * @since ：2023-08-15
 */
@Aspect
@Component
@Order(55)
public class LimitAop {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private final StringRedisTemplate template;

    /**
     * 功能描述: <br>
     * 〈是否重复提交〉
     *
     * @Param: [pj, nrs]
     * @Return: java.lang.Object
     * @Author: FuX
     * @Update:
     * @Date: 2023/8/15 10:26
     */
    @Around(value = "execution(* xyz.hzxiao.controller..*(..)) && @annotation(nrs)")
    public Object around(ProceedingJoinPoint pj, Limit nrs) throws Throwable {
        ValueOperations<String, String> ops = template.opsForValue();
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            String key = request.getRemoteAddr() + "-" + request.getServletPath();
            boolean absent = Boolean.TRUE.equals(ops.setIfAbsent(key, "0", nrs.LIMIT_TIME(), nrs.UNIT()));
            return absent ? pj.proceed() : "点击的太快了，歇息一下叭";
        } catch (Throwable ex) {
            log.error("验证重复提交错误", ex);
            throw ex;
        }
    }

    public LimitAop(StringRedisTemplate template) {
        this.template = template;
    }
}
